package craky.componentc;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Image;
import java.awt.Insets;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.text.Format;

import javax.swing.JFormattedTextField;
import javax.swing.border.Border;

import craky.util.TextExtender;
import craky.util.UIResourceManager;
import craky.util.UIUtil;

public class JCFormattedTextField extends JFormattedTextField
{
    private static final long serialVersionUID = -2877157868704955530L;
    
    private Image image;
    
    private float alpha;
    
    private boolean imageOnly;
    
    private Border normalBorder;
    
    private Border rolloverBorder;
    
    private Border nonEditableBorder;
    
    private Border nonEditableRolloverBorder;
    
    private Border disabledBorder;
    
    private Insets visibleInsets;
    
    private MouseListener listener;
    
    private boolean borderChange;
    
    private TextExtender extender;
    
    public JCFormattedTextField()
    {
        super();
        init();
    }
    
    public JCFormattedTextField(Object value)
    {
        super(value);
        init();
    }
    
    public JCFormattedTextField(Format format)
    {
        super(format);
        init();
    }
    
    public JCFormattedTextField(AbstractFormatter formatter)
    {
        super(formatter);
        init();
    }
    
    public JCFormattedTextField(AbstractFormatterFactory factory)
    {
        super(factory);
        init();
    }
    
    public JCFormattedTextField(AbstractFormatterFactory factory, Object currentValue)
    {
        super(factory, currentValue);
        init();
    }

    public void init()
    {
        setUI(new CFormattedTextFieldUI());
        super.setOpaque(false);
        setFont(UIUtil.getDefaultFont());
        setBackground(UIResourceManager.getWhiteColor());
        setForeground(Color.BLACK);
        setCaretColor(Color.BLACK);
        setSelectionColor(new Color(49, 106, 197));
        setSelectedTextColor(UIResourceManager.getWhiteColor());
        setDisabledTextColor(new Color(123, 123, 122));
        setCursor(new Cursor(Cursor.TEXT_CURSOR));
        setMargin(new Insets(0, 0, 0, 0));
        super.setBorder(normalBorder = new ImageBorder(UIResourceManager.getImageByName("border_normal.png"), 5, 6, 3, 4));
        extender = new TextExtender(this);
        rolloverBorder = UIResourceManager.getBorder(UIResourceManager.KEY_TEXT_ROLLOVER_BORDER);
        nonEditableBorder = UIResourceManager.getBorder(UIResourceManager.KEY_TEXT_NON_EDITABLE_BORDER);
        nonEditableRolloverBorder = UIResourceManager.getBorder(UIResourceManager.KEY_TEXT_NON_EDITABLE_ROLLOVER_BORDER);
        disabledBorder = UIResourceManager.getBorder(UIResourceManager.KEY_TEXT_DISABLED_BORDER);
        alpha = 1.0f;
        visibleInsets = new Insets(1, 1, 1, 1);
        borderChange = true;
        listener = new MouseAdapter()
        {
            public void mouseEntered(MouseEvent e)
            {
                mouseIn();
            }

            public void mouseExited(MouseEvent e)
            {
                mouseOut();
            }
        };
        
        addMouseListener(listener);
    }
    
    public float getAlpha()
    {
        return alpha;
    }

    public void setAlpha(float alpha)
    {
        if(alpha >= 0.0f && alpha <= 1.0f)
        {
            this.alpha = alpha;
            this.repaint();
        }
        else
        {
            throw new IllegalArgumentException("Invalid alpha:" + alpha);
        }
    }

    public Image getImage()
    {
        return image;
    }

    public void setImage(Image image)
    {
        this.image = image;
        this.repaint();
    }
    
    @Deprecated
    public void updateUI()
    {}
    
    @Deprecated
    public void setOpaque(boolean isOpaque)
    {}

    public Insets getVisibleInsets()
    {
        return visibleInsets;
    }

    public void setVisibleInsets(int top, int left, int bottom, int right)
    {
        this.visibleInsets.set(top, left, bottom, right);
        this.repaint();
    }
    
    public boolean isImageOnly()
    {
        return imageOnly;
    }

    public void setImageOnly(boolean imageOnly)
    {
        this.imageOnly = imageOnly;
        this.repaint();
    }
    
    public void setBorder(Border border)
    {
        this.normalBorder = border;
        
        if(border == null && visibleInsets != null)
        {
            visibleInsets.set(0, 0, 0, 0);
        }
        
        super.setBorder(border);
    }
    
    public void setEditable(boolean editable)
    {
        super.setEditable(editable);
        
        if(borderChange)
        {
            mouseOut();
        }
    }
    
    public void setEnabled(boolean enabled)
    {
        super.setEnabled(enabled);
        
        if(borderChange)
        {
            if(enabled)
            {
                mouseOut();
            }
            else if(normalBorder != null)
            {
                super.setBorder(disabledBorder);
            }
        }
    }
    
    public boolean isPopupMenuEnabled()
    {
        return extender.isPopupMenuEnabled();
    }

    public void setPopupMenuEnabled(boolean popupMenuEnabled)
    {
        extender.setPopupMenuEnabled(popupMenuEnabled);
    }
    
    private void mouseIn()
    {
        if(normalBorder != null && isEnabled())
        {
            super.setBorder(isEditable()? rolloverBorder: nonEditableRolloverBorder);
        }
    }
    
    private void mouseOut()
    {
        if(normalBorder != null && isEnabled())
        {
            super.setBorder(isEditable()? normalBorder: nonEditableBorder);
        }
    }
    
    public void clearBorderListener()
    {
        this.removeMouseListener(listener);
        borderChange = false;
    }
}